package com.javaobj.auth.security.jwt;

import com.google.common.base.Strings;
import com.javaobj.auth.accesstoken.AccessTokenException;
import com.javaobj.auth.accesstoken.AccessTokenService;
import com.nimbusds.jose.*;
import com.nimbusds.jose.crypto.MACSigner;
import com.nimbusds.jose.crypto.MACVerifier;
import com.nimbusds.jwt.JWTClaimsSet;
import com.nimbusds.jwt.SignedJWT;

import java.text.ParseException;
import java.util.Date;
import java.util.Map;
import java.util.concurrent.TimeUnit;


public class JWTAccessTokenService implements AccessTokenService {


    private final String keyValue;

    private final String algorithm;


    public JWTAccessTokenService(String keyValue, String algorithm) {
        this.keyValue = keyValue;
        this.algorithm = algorithm;
    }


    @Override
    public String encode(Map<String, Object> params) throws AccessTokenException {

        try {
            JWSSigner signer = new MACSigner(keyValue);

            JWTClaimsSet.Builder claimsSetBuilder = new JWTClaimsSet.Builder()
                    .subject("csbaic")
                    .issuer("https://www.csbaic.com/")
                    .expirationTime(new Date(System.currentTimeMillis() + TimeUnit.DAYS.toMillis(180)));


            if(params != null){
                for(Map.Entry<String, Object> entry : params.entrySet()){
                    claimsSetBuilder.claim(entry.getKey(), entry.getValue());
                }
            }

            SignedJWT signedJWT = new SignedJWT(new JWSHeader(JWSAlgorithm.parse(algorithm)), claimsSetBuilder.build());
            signedJWT.sign(signer);

            return signedJWT.serialize();

        } catch (JOSEException e) {
            throw new AccessTokenException(e);
        }
    }

    @Override
    public Map<String, Object> decode(String token) throws AccessTokenException {
        if(Strings.isNullOrEmpty(token)){
            throw new AccessTokenException("token == null");
        }

        try {
            SignedJWT signedJWT = SignedJWT.parse(token);
            JWSVerifier verifier = new MACVerifier(keyValue);
            signedJWT.verify(verifier);

            JWTClaimsSet claimsSet = signedJWT.getJWTClaimsSet();
            // TODO: 2020/2/8 检查是超时
            return claimsSet.getClaims();
        } catch (JOSEException | ParseException e) {
            throw new AccessTokenException(e);
        }
    }


}
